interface Point {
  x: number
  y: number
}

interface Size {
  width: number
  height: number
}

interface AreaConfig {
  id: string
  name: string
  size: Size
  position?: Point
  type: 'raw' | 'wip' | 'finished'
  rows: number
  cols: number
  direction: 'horizontal' | 'vertical'
  connections?: string[]  // 与哪些区域相连
}

export class LayoutCalculator {
  private areas: Map<string, AreaConfig>
  private spacing: number
  private canvasSize: Size

  constructor(spacing: number = 50) {
    this.areas = new Map()
    this.spacing = spacing
    this.canvasSize = { width: 0, height: 0 }
  }

  // 添加区域
  addArea(config: AreaConfig) {
    this.areas.set(config.id, config)
  }

  // 计算布局
  calculateLayout(): Map<string, AreaConfig> {
    // 1. 首先计算每个区域的实际大小
    this.calculateAreaSizes()

    // 2. 根据连接关系创建布局图
    const graph = this.createConnectionGraph()

    // 3. 使用力导向算法计算布局
    this.forceDirectedLayout(graph)

    // 4. 调整布局避免重叠
    this.adjustOverlapping()

    // 5. 计算画布大小
    this.calculateCanvasSize()

    return this.areas
  }

  private calculateAreaSizes() {
    this.areas.forEach(area => {
      const totalWidth = area.cols * area.size.width + (area.cols - 1) * this.spacing
      const totalHeight = area.rows * area.size.height + (area.rows - 1) * this.spacing
      
      area.size = {
        width: area.direction === 'horizontal' ? totalWidth : area.size.width,
        height: area.direction === 'vertical' ? totalHeight : area.size.height
      }
    })
  }

  private createConnectionGraph() {
    const graph = new Map<string, string[]>()
    
    this.areas.forEach((area, id) => {
      if (area.connections) {
        graph.set(id, area.connections)
      } else {
        graph.set(id, [])
      }
    })

    return graph
  }

  private forceDirectedLayout(graph: Map<string, string[]>) {
    const iterations = 100
    const k = 100 // 弹簧系数
    const temperature = 0.1 // 温度系数

    // 初始化随机位置
    this.areas.forEach(area => {
      if (!area.position) {
        area.position = {
          x: Math.random() * 1000,
          y: Math.random() * 1000
        }
      }
    })

    // 力导向迭代
    for (let i = 0; i < iterations; i++) {
      const forces = new Map<string, Point>()
      
      // 计算排斥力
      this.areas.forEach((area1, id1) => {
        forces.set(id1, { x: 0, y: 0 })
        
        this.areas.forEach((area2, id2) => {
          if (id1 !== id2) {
            const dx = area1.position!.x - area2.position!.x
            const dy = area1.position!.y - area2.position!.y
            const distance = Math.sqrt(dx * dx + dy * dy)
            
            if (distance > 0) {
              const force = k * k / distance
              const force_x = force * dx / distance
              const force_y = force * dy / distance
              
              const currentForce = forces.get(id1)!
              forces.set(id1, {
                x: currentForce.x + force_x,
                y: currentForce.y + force_y
              })
            }
          }
        })
      })

      // 计算吸引力
      graph.forEach((connections, id1) => {
        connections.forEach(id2 => {
          const area1 = this.areas.get(id1)!
          const area2 = this.areas.get(id2)!
          
          const dx = area1.position!.x - area2.position!.x
          const dy = area1.position!.y - area2.position!.y
          const distance = Math.sqrt(dx * dx + dy * dy)
          
          const force = distance * distance / k
          const force_x = force * dx / distance
          const force_y = force * dy / distance
          
          const currentForce = forces.get(id1)!
          forces.set(id1, {
            x: currentForce.x - force_x,
            y: currentForce.y - force_y
          })
        })
      })

      // 更新位置
      forces.forEach((force, id) => {
        const area = this.areas.get(id)!
        area.position = {
          x: area.position!.x + force.x * temperature,
          y: area.position!.y + force.y * temperature
        }
      })
    }
  }

  private adjustOverlapping() {
    let hasOverlap = true
    const padding = this.spacing

    while (hasOverlap) {
      hasOverlap = false

      this.areas.forEach((area1, id1) => {
        this.areas.forEach((area2, id2) => {
          if (id1 !== id2) {
            const overlap = this.calculateOverlap(area1, area2, padding)
            if (overlap) {
              hasOverlap = true
              
              // 移动重叠的区域
              const dx = overlap.x / 2
              const dy = overlap.y / 2
              
              area1.position = {
                x: area1.position!.x + dx,
                y: area1.position!.y + dy
              }
              
              area2.position = {
                x: area2.position!.x - dx,
                y: area2.position!.y - dy
              }
            }
          }
        })
      })
    }
  }

  private calculateOverlap(area1: AreaConfig, area2: AreaConfig, padding: number): Point | null {
    const left1 = area1.position!.x
    const right1 = area1.position!.x + area1.size.width
    const top1 = area1.position!.y
    const bottom1 = area1.position!.y + area1.size.height

    const left2 = area2.position!.x
    const right2 = area2.position!.x + area2.size.width
    const top2 = area2.position!.y
    const bottom2 = area2.position!.y + area2.size.height

    const overlapX = Math.min(right1, right2) - Math.max(left1, left2) + padding
    const overlapY = Math.min(bottom1, bottom2) - Math.max(top1, top2) + padding

    if (overlapX > 0 && overlapY > 0) {
      return { x: overlapX, y: overlapY }
    }

    return null
  }

  private calculateCanvasSize() {
    let maxX = 0
    let maxY = 0

    this.areas.forEach(area => {
      const rightEdge = area.position!.x + area.size.width
      const bottomEdge = area.position!.y + area.size.height

      maxX = Math.max(maxX, rightEdge)
      maxY = Math.max(maxY, bottomEdge)
    })

    this.canvasSize = {
      width: maxX + this.spacing,
      height: maxY + this.spacing
    }
  }

  // 获取画布大小
  getCanvasSize(): Size {
    return this.canvasSize
  }
} 